import { classnames } from 'classnames';
/*
 * @Descripttion: 
 * @Author: ziwei
 * @Date: 2022-07-05 10:46:18
 * @LastEditors: ziwei
 * @LastEditTime: 2022-07-06 14:33:08
 */
export {}

interface Animal{
    name:string
    age:number
}
interface Person{
    name:string
    age:number
    gender:number
}
function getName(a:Animal):string{
    return a.name
}
let a:Animal={
    name:'',
    age:10
}
getName(a)

let p:Person = {
    name:'',
    age:10,
    gender:0
}
getName(p)

//基本数据类型的兼容
let num:string|number
let str:string = 'xx'
num = str
let num2:{
    toString():string
}
let str2:string = 'jiagou'
num2 = str2;
// str2 = num2 不行，没有的方法会属性可能会报错

//类的兼容性 看形状
namespace ab{
    class Animal{}
    class Bird extends Animal{}
    let a:Animal;
    let b:Bird;
    // a=b;
    // b=a;
}

//函数的兼容性 ！！难点   :interface描述函数的时候写 其他时候都是箭头
//比较参数 比较返回值
//少接收可以 多接收不可以
type Func = (a:number,b:number)=>void;
let sum:Func
function f1(a:number,b:number):void{
}
sum = f1;
//少一个 少2个参数都可以
function f2(a:number):void{}
sum =f2

//比较返回值 
type GetPerson = ()=>{name:string,age:number}
let getPerson:GetPerson
function g1(){
    return {name:'xx',age:10}
}
function g2(){
    return {name:'xx',age:10,gender:0}
}

//一切的一切都是为了类型安全，为了使用的时候不报错
//返回值类型是协变得，而参数类型是逆变的
//返回值类型可以传子类，参数可以传父类
//参数逆变父类，返回值协变子类 搀你父 返鞋子


class Animal{}
class Dog extends Animal{
    public name:string = 'Dog'
}
class BlackDog extends Dog{
    public age: number= 10
}
class WhiteDog extends Dog{
    public home:string = '北京'
}
let animal:Animal;
let dog:Dog;
let blackDog:BlackDog
let whiteDog:WhiteDog
type Callback = (dog:Dog)=>Dog;
function exec(callback:Callback):void{
    callback(whiteDog)
}
/**
 * 参数可以传自己和自己的父类
 * 返回值可以传自己和自己的子类
 * 四种情况
 * 1.参数传子类返回值子类
 * 2.参数是子类返回值是父类
 * 3.参数是父类返回值是父类
 * 3.参数是父类返回值是子类
 */

type ChildToChild = (blackDog:BlackDog)=>BlackDog//N
let childToChild:ChildToChild;
type ChildToParent = (blackDog:BlackDog)=>Animal //N
type ParentToParent = (animal:Animal)=>Animal //N
type ParentToChild = (animal:Animal)=>BlackDog  //Y
/**
 * 能处理动物可以传入狗
 * 返回一条狗，可以是黑狗
 * 参数逆变父类，返回值协变子类 搀你父 返鞋子
 */
//ts中参数是双向协变得